﻿using Aliyun.OSS;
using Aliyun.OSS.Common;
using Aspose.Slides;
using Dapper;
using FreeRedis;
using MySql.Data.MySqlClient;
using Newtonsoft.Json;
using PdfiumViewer;
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.IO;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using WhiteBoardService.Entity;

namespace WhiteBoardService
{
    public class Program
    {
        private const string createsql = @"CREATE TABLE IF NOT EXISTS `room_whiteboardhistory_{0}`  (
  `cid` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '课程ID',
  `idx` bigint(20) NULL DEFAULT NULL COMMENT '课程中的图片ID',
  `json` text CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL COMMENT '记录json文件',
  `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
  `md5` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT 'history md5',
  PRIMARY KEY (`id`) USING BTREE,
  UNIQUE INDEX `room_whiteboardhistory_cid_idx1`(`cid`, `idx`) USING BTREE,
  INDEX `room_whiteboardhistory_cid_IDX`(`cid`) USING BTREE,
  INDEX `room_whiteboardhistory_idx_IDX`(`idx`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 27 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = Dynamic COMMENT='课件笔迹';";

        private readonly static string alioss_endpoint = ConfigurationManager.AppSettings["alioss_endpoint"];
        private readonly static string alioss_region = ConfigurationManager.AppSettings["alioss_region"];
        private readonly static string alioss_accessKeyId = ConfigurationManager.AppSettings["alioss_accessKeyId"];
        private readonly static string alioss_accessKeySecret = ConfigurationManager.AppSettings["alioss_accessKeySecret"];
        private readonly static string alioss_bucketName = ConfigurationManager.AppSettings["alioss_bucketName"];
        private readonly static string alioss_prefixPath = ConfigurationManager.AppSettings["alioss_prefixPath"];
        private readonly static string _conn = ConfigurationManager.AppSettings["QyhWhiteboardDb"];
        private readonly static string loopurl = ConfigurationManager.AppSettings["qyh_timer_server"];
        private readonly static string write_errorlog = ConfigurationManager.AppSettings["write_errorlog"];

        private readonly static string redisConf = ConfigurationManager.AppSettings["RedisConf"];
        // redis
        public static RedisClient _redis = new RedisClient(redisConf);
        static void Main(string[] args)
        {

            Thread newThread1 = new Thread(new ThreadStart(fileTaks));
            newThread1.Start();

            Task.Run(async () => await pushTask());

            Thread newThread2 = new Thread(new ThreadStart(createTable));
            newThread2.Start();

            Task.Run(async () => await LoopServer());

            try
            {
                _redis.Get($"ynxp.fun");
            }
            catch (Exception ex)
            {
                WriteErrLog($"[redis 访问失败{ex.Message}]");
            }
            Console.ReadLine();
        }
        /// <summary>
        /// 处理文件
        /// </summary>
        private static void fileTaks()
        {
            Console.WriteLine("文件任务开启...");
            // 设置上传目录
            var uploadPath = AppDomain.CurrentDomain.BaseDirectory + "/Uploads";
            while (true)
            {
                Thread.Sleep(5000);

                // 如果目录不存在则创建
                if (!Directory.Exists(uploadPath))
                {
                    Directory.CreateDirectory(uploadPath);
                }

                try
                {
                    List<FileTasks> list = null;
                    //数据库
                    using (MySqlConnection conn = new MySqlConnection(_conn))
                    {
                        if (conn.State != ConnectionState.Open)
                        {
                            conn.Open();
                        }
                        list = conn.Query<FileTasks>("select * from file_tasks where state = 0 limit 10;", null, commandType: CommandType.Text).ToList();
                    }
                    if (list?.Count > 0)
                    {
                        for (int i = 0; i < list.Count; i++)
                        {
                            if (!string.IsNullOrWhiteSpace(list[i].files))
                            {
                                var fileurls = list[i].files.Split('|');
                                for (int f = 0; f < fileurls.Length; f++)
                                {
                                    // 获取原始文件名
                                    var fileExtension = Path.GetExtension(fileurls[f]).ToLower();
                                    var fileName = Path.GetFileNameWithoutExtension(fileurls[f]);
                                    // 本地文件地址
                                    var converPath = uploadPath + "/" + fileName;
                                    // 如果目录不存在则创建
                                    if (!Directory.Exists(converPath))
                                    {
                                        Directory.CreateDirectory(converPath);
                                    }
                                    try
                                    {
                                        RoomSources _info = null;
                                        using (MySqlConnection conn = new MySqlConnection(_conn))
                                        {
                                            if (conn.State != ConnectionState.Open)
                                            {
                                                conn.Open();
                                            }
                                            _info = conn.Query<RoomSources>("select * from room_sources where cid = @cid", new { cid = list[i].cid }, commandType: CommandType.Text).FirstOrDefault();
                                            if (_info == null)
                                            {
                                                _info = new RoomSources()
                                                {
                                                    cid = list[i].cid,
                                                    pages = ""
                                                };
                                                if (conn.Execute($"insert into room_sources (cid,pages,uploading,uptime)values(@cid,'',1,now())", new { cid = list[i].cid }, commandType: CommandType.Text) > 0)
                                                {
                                                }
                                            }
                                            else
                                            {
                                                if (conn.Execute($"update room_sources set uploading = 1,uptime=now() where cid = @cid", new { cid = list[i].cid }, commandType: CommandType.Text) > 0)
                                                {

                                                }
                                            }

                                            // 加入缓存
                                            _redis.Set($"sources:{list[i].cid}", 1, 3600);
                                        }
                                        // 当前课件中最大的id
                                        int maxIndex = 0;
                                        // 页码索引
                                        int[] pagenums = null;
                                        // 判断页面
                                        if (!string.IsNullOrWhiteSpace(_info.pages) && !string.IsNullOrEmpty(_info.pages))
                                        {
                                            try
                                            {
                                                pagenums = JsonConvert.DeserializeObject<int[]>($"[{_info.pages}]");
                                                if (pagenums?.Length > 0)
                                                {
                                                    maxIndex = pagenums.Max();
                                                }
                                                else
                                                {
                                                    pagenums = null;
                                                }
                                            }
                                            catch (Exception)
                                            {
                                                pagenums = null;
                                            }
                                        }
                                        List<int> pagelist = new List<int>();
                                        switch (fileExtension)
                                        {
                                            case ".doc":
                                                break;
                                            case ".docx":
                                                break;
                                            case ".ppt":
                                            case ".pptx":
                                                pagelist = ConvertPPTtoImages(fileurls[f], converPath, maxIndex);
                                                break;
                                            case ".pdf":
                                                pagelist = ConvertPDFtoImages(fileurls[f], converPath, maxIndex);
                                                break;
                                            case ".png":
                                            case ".jpg":
                                                pagelist = ConvertJPGtoImages(fileurls[f], converPath, maxIndex);
                                                break;
                                            default:
                                                break;
                                        }
                                        // 上传到ali_oss
                                        var res = uploadOss(list[i].cid, pagelist, converPath);
                                        // 修改数据库
                                        string _pageStr = "";
                                        if (!string.IsNullOrEmpty(_info?.pages) && !string.IsNullOrWhiteSpace(_info?.pages))
                                        {
                                            _pageStr = _info.pages + "," + string.Join(",", pagelist);
                                        }
                                        else
                                        {
                                            _pageStr = string.Join(",", pagelist);
                                        }

                                        //查询数据库
                                        using (MySqlConnection conn = new MySqlConnection(_conn))
                                        {
                                            try
                                            {
                                                if (conn.State != ConnectionState.Open)
                                                {
                                                    conn.Open();
                                                }
                                                if (conn.Execute($"update room_sources set uploading=0,pages=@pages,uptime=null  where cid = @cid", new { cid = list[i].cid, pages = _pageStr }, commandType: CommandType.Text) > 0)
                                                {

                                                }
                                                if (conn.Execute($"update file_tasks set state=1 where id = @id", new { id = list[i].id }, commandType: CommandType.Text) > 0)
                                                {

                                                }

                                                // 加入缓存
                                                _redis.Set($"sources:{list[i].cid}", 0, 3600);
                                            }
                                            catch (Exception)
                                            {

                                            }
                                        }
                                    }
                                    catch (Exception)
                                    {

                                    }
                                    finally
                                    {
                                        // 删除文件夹
                                        DeleteDirectory(converPath);
                                        // 删除源文件
                                        File.Delete(fileurls[f]);
                                    }
                                }
                            }
                        }
                    }
                }
                catch (Exception)
                {

                }
                GC.Collect();
            }
        }
        /// <summary>
        /// 推送补偿
        /// </summary>
        private static async Task pushTask()
        {
            Console.WriteLine("错误补偿任务已开启...");
            while (true)
            {
                Thread.Sleep(10000);

                List<PushLiveInfo> list = null;
                //数据库
                using (MySqlConnection conn = new MySqlConnection(_conn))
                {
                    if (conn.State != ConnectionState.Open)
                    {
                        conn.Open();
                    }
                    list = conn.Query<PushLiveInfo>("select * from push_liveinfo where state = 0 limit 10;", null, commandType: CommandType.Text).ToList();
                }

                for (int i = 0; i < list.Count; i++)
                {
                    //直播间已结束，发送回调
                    using (var client = new HttpClient())
                    {
                        try
                        {
                            HttpResponseMessage response = await client.GetAsync(list[i].url);
                            response.EnsureSuccessStatusCode();
                            string responseBody = await response.Content.ReadAsStringAsync();

                            //数据库
                            using (MySqlConnection conn = new MySqlConnection(_conn))
                            {
                                if (conn.State != ConnectionState.Open)
                                {
                                    conn.Open();
                                }
                                if (conn.Execute($"update push_liveinfo set state=1 where id = @id", new { id = list[i].id }, commandType: CommandType.Text) > 0)
                                {

                                }
                            }
                        }
                        catch (HttpRequestException ex)
                        {

                        }
                    }
                }
            }
        }

        /// <summary>
        /// 处理
        /// </summary>
        private static void createTable()
        {
            while (true)
            {
                Thread.Sleep(3600000);
                var nowTime = DateTime.Now;
                var t1_name = nowTime.ToString("yyyyMM");
                var t2_name = nowTime.AddMonths(1).ToString("yyyyMM");
                var t3_name = nowTime.AddMonths(2).ToString("yyyyMM");
                var t4_name = nowTime.AddMonths(3).ToString("yyyyMM");
                var t5_name = nowTime.AddMonths(4).ToString("yyyyMM");
                //数据库
                using (MySqlConnection conn = new MySqlConnection(_conn))
                {
                    if (conn.State != ConnectionState.Open)
                    {
                        conn.Open();
                    }
                    if (conn.Execute(string.Format(createsql, t1_name), null, commandType: CommandType.Text) > 0)
                    {
                    }
                    if (conn.Execute(string.Format(createsql, t2_name), null, commandType: CommandType.Text) > 0)
                    {
                    }
                    if (conn.Execute(string.Format(createsql, t3_name), null, commandType: CommandType.Text) > 0)
                    {
                    }
                    if (conn.Execute(string.Format(createsql, t4_name), null, commandType: CommandType.Text) > 0)
                    {
                    }
                    if (conn.Execute(string.Format(createsql, t5_name), null, commandType: CommandType.Text) > 0)
                    {
                    }
                }
            }
        }

        /// <summary>
        /// 定时唤醒
        /// </summary>
        private static async Task LoopServer()
        {
            string[] urls = null;
            if (!string.IsNullOrWhiteSpace(loopurl))
            {
                urls = loopurl.Split(',');
            }
            if (urls?.Length > 0)
            {
                while (true)
                {
                    Thread.Sleep(10000);
                    for (int i = 0; i < urls.Length; i++)
                    {
                        //直播间已结束，发送回调
                        using (var client = new HttpClient())
                        {
                            try
                            {
                                HttpResponseMessage response = await client.GetAsync(urls[i]);
                                response.EnsureSuccessStatusCode();
                                string responseBody = await response.Content.ReadAsStringAsync();
                            }
                            catch (Exception)
                            {

                            }
                        }
                    }
                }
            }
        }

        #region 工具

        /// <summary>
        /// PPT to images
        /// </summary>
        /// <param name="pptPath"></param>
        /// <param name="outputFolder"></param>
        /// <param name="maxIndex"></param>
        /// <returns></returns>
        public static List<int> ConvertPPTtoImages(string pptPath, string outputFolder, int maxIndex)
        {
            List<int> res = new List<int>();
            Presentation presentation = new Presentation(pptPath);
            var size = presentation.SlideSize;
            // 导出每页为图片
            int i = 0;
            foreach (Slide slide in presentation.Slides)
            {
                string imagePath = Path.Combine(outputFolder, $"{maxIndex + i + 1}.jpg");
                slide.GetThumbnail(2, 2).Save(imagePath);
                res.Add(maxIndex + i + 1);
                i++;
            }
            GC.Collect();
            return res;
        }

        ///// <summary>
        ///// 将PPT转成Images 【需要安装office版本】
        ///// </summary>
        ///// <param name="pptPath"></param>
        ///// <param name="outputFolder"></param>
        //public List<int> ConvertPPTtoImages(string pptPath, string outputFolder, int maxIndex)
        //{
        //    List<int> res = new List<int>();
        //    // 创建PowerPoint应用程序对象
        //    Application pptApplication = new Application();
        //    Presentation presentation = null;
        //    try
        //    {
        //        // 打开PPT文件
        //        presentation = pptApplication.Presentations.Open(pptPath,
        //            MsoTriState.msoFalse,
        //            MsoTriState.msoFalse,
        //            MsoTriState.msoFalse);

        //        // 确保输出目录存在
        //        if (!Directory.Exists(outputFolder))
        //        {
        //            Directory.CreateDirectory(outputFolder);
        //        }
        //        WriteLog("4", outputFolder);
        //        int i = 0;
        //        // 导出每页为图片
        //        foreach (Slide slide in presentation.Slides)
        //        {
        //            string imagePath = Path.Combine(outputFolder, $"{maxIndex + i + 1}.jpg");
        //            WriteLog("4-1", imagePath);
        //            slide.Export(imagePath, "JPEG", 1920, 1080); // 可调整分辨率
        //            res.Add(maxIndex + i + 1);
        //            i++;
        //        }

        //        return res;
        //    }
        //    catch (Exception ex)
        //    {
        //        WriteLog("5", ex.Message);
        //    }
        //    finally
        //    {
        //        // 关闭PPT文件并退出应用程序
        //        if (presentation != null)
        //        {
        //            presentation.Close();
        //            Marshal.FinalReleaseComObject(presentation);
        //        }

        //        if (pptApplication != null)
        //        {
        //            pptApplication.Quit();
        //            Marshal.FinalReleaseComObject(pptApplication);
        //        }
        //    }

        //    return res;
        //}

        /// <summary>
        /// 将PPT转成Images
        /// </summary>
        /// <param name="pptPath"></param>
        /// <param name="outputFolder"></param>
        public static List<int> ConvertPDFtoImages(string PDFPath, string outputFolder, int maxIndex)
        {
            List<int> res = new List<int>();
            try
            {
                int pageCount = 0;
                // 加载PDF文档并获取页面尺寸
                using (var document = PdfDocument.Load(PDFPath))
                {
                    pageCount = document.PageCount;//pdf页码
                    var pdfSize = document.PageSizes;

                    for (int i = 0; i < pageCount; i++)
                    {
                        System.Drawing.Size size = new System.Drawing.Size();
                        //pdfSize为list类型，索引从0，而pdf页码从1开始，所以需要-1
                        size.Width = (int)pdfSize[i].Width;
                        size.Height = (int)pdfSize[i].Height;
                        var image = document.Render(i, size.Width, size.Height, 300, 300, PdfiumViewer.PdfRenderFlags.Annotations);
                        try
                        {
                            image.Save($"{outputFolder}/{maxIndex + i + 1}.jpg");
                        }
                        catch (Exception)
                        {

                        }
                        image.Dispose();
                        // res
                        res.Add(maxIndex + i + 1);
                    }
                }
                return res;
            }
            catch (Exception)
            {

            }
            return res;
        }

        /// <summary>
        /// 将JPG/PNG转成Images
        /// </summary>
        /// <param name="pptPath"></param>
        /// <param name="outputFolder"></param>
        public static List<int> ConvertJPGtoImages(string JPGPath, string outputFolder, int maxIndex)
        {
            List<int> res = new List<int>();
            // 重命名文件
            File.Move(JPGPath, $"{outputFolder}/{maxIndex + 1}.jpg");
            res.Add(maxIndex + 1);
            return res;
        }


        /// <summary>
        /// 上传到阿里云OSS
        /// </summary>
        /// <returns></returns>
        public static bool uploadOss(string classid, List<int> pagelist, string filepath)
        {
            // 创建ClientConfiguration实例，按照您的需要修改默认参数。
            var conf = new ClientConfiguration();
            // 设置v4签名。
            conf.SignatureVersion = SignatureVersion.V4;
            // 创建OssClient实例。
            var client = new OssClient(alioss_endpoint, alioss_accessKeyId, alioss_accessKeySecret, conf);
            // 设置Region
            client.SetRegion(alioss_region);
            // 设置前缀
            string prefix = string.Empty;
            if (!string.IsNullOrEmpty(alioss_prefixPath) && !string.IsNullOrWhiteSpace(alioss_prefixPath))
            {
                prefix = $"{alioss_prefixPath}/";
            }
            try
            {
                for (int i = 0; i < pagelist.Count; i++)
                {
                    // 上传文件。
                    var result = client.PutObject(alioss_bucketName, $"{prefix}{classid}/{pagelist[i]}.jpg", $"{filepath}/{pagelist[i]}.jpg");
                }
            }
            catch (Exception ex)
            {

            }
            return true;
        }

        /// <summary>
        /// 删除文件夹
        /// </summary>
        /// <param name="target_dir"></param>
        public static void DeleteDirectory(string target_dir)
        {
            string[] files = Directory.GetFiles(target_dir);
            string[] dirs = Directory.GetDirectories(target_dir);

            foreach (string file in files)
            {
                File.SetAttributes(file, FileAttributes.Normal); // 移除只读属性，如果需要的话
                File.Delete(file); // 删除文件
            }

            foreach (string dir in dirs)
            {
                DeleteDirectory(dir); // 递归删除子文件夹
            }

            Directory.Delete(target_dir, false); // 现在文件夹是空的，可以删除它了
        }



        /// <summary>
        /// 错误日志写入
        /// </summary>
        /// <param name="strErrCode"></param>
        public static void WriteErrLog(string strErrCode)
        {
            if (write_errorlog != "1") return;
            // 设置上传目录
            var uploadPath = AppDomain.CurrentDomain.BaseDirectory + "/Logs";
            // 如果目录不存在则创建
            if (!Directory.Exists(uploadPath))
            {
                Directory.CreateDirectory(uploadPath);
            }
            string strFileName = uploadPath + "\\ErrorLog" + System.DateTime.Now.ToString("yyyyMMdd") + ".txt";

            StreamWriter sw = File.AppendText(strFileName);
            try
            {
                sw.WriteLine(System.DateTime.Now.ToString() + "," + strErrCode);
                sw.Flush();
            }
            catch
            {
                return;
            }
            finally
            {
                sw.Close();
            }
        }
        #endregion
    }
}
